/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package arbol_sintactico_abstracto;

import analizadorlexico.Token;
import tabla_de_simbolos.Atributo;
import tabla_de_simbolos.Clase;
import tabla_de_simbolos.ErrorSemantico;
import tabla_de_simbolos.Constructor;
import tabla_de_simbolos.TablaDeSimbolos;
import tabla_de_simbolos.Tipo;
import generador_de_codigo.GeneradorDeCodigo;
import java.io.IOException;
import tabla_de_simbolos.Metodo;
/**
 *
 * @author Javi
 */
public class Asignacion extends Sentencia {
    private Token ladoIzq;
    private Expresion ladoDer;

    public Asignacion(Token ladoIzq, Expresion ladoDer, Token simbolo) {
        this.token = simbolo;
        this.ladoIzq = ladoIzq;
        this.ladoDer = ladoDer;
    }

    public Token getLadoIzq() {
        return ladoIzq;
    }

    public void setLadoIzq(Token ladoIzq) {
        this.ladoIzq = ladoIzq;
    }

    public Expresion getLadoDer() {
        return ladoDer;
    }

    public void setLadoDer(Expresion ladoDer) {
        this.ladoDer = ladoDer;
    }

    public Token getSimbolo() {
        return token;
    }

    public void setSimbolo(Token simbolo) {
        this.token = simbolo;
    }
    
    @Override
    public Tipo check(Clase clase, Constructor metodo, TablaDeSimbolos ts) throws ErrorSemantico, IOException {
        Tipo tipoDer = ladoDer.check(clase, metodo, ts);
        Tipo tipoIzq = null;
        int offset;
        for(Atributo param : metodo.getParametros()){
            if(param.getNombre().equals(ladoIzq.getLexema())){
                tipoIzq = param.getTipo();
                if(((Metodo)metodo).getModMetodo().getModificador().equals("dynamic"))
                    offset = metodo.getOffsetParam() - param.getOffset() + 3;
                else
                    offset = metodo.getOffsetParam() - param.getOffset() + 2;
                
                GeneradorDeCodigo.generar("STORE " + offset + "\n");
                break;
            }            
        }
        
        if(tipoIzq == null){
            for(Atributo var : metodo.getVariables()){
                if(var.getNombre().equals(ladoIzq.getLexema())){
                    tipoIzq = var.getTipo();
                    offset = var.getOffset();
                    GeneradorDeCodigo.generar("STORE " + offset + "\n");
                    break;
                }            
            }            
        }
        
        if(tipoIzq == null){
            if(metodo.getModMetodo().getModificador().equals("static"))
                throw new ErrorSemantico("la variable '" + ladoIzq.getLexema() + "' no es accesible para metodo estatico. Linea: " + ladoIzq.getLinea());
            for(Atributo var : clase.getListaAtributos()){
                if(var.getNombre().equals(ladoIzq.getLexema())){
                    tipoIzq = var.getTipo();
                    offset = var.getOffset();
                    GeneradorDeCodigo.generar("LOAD 3 \n");
                    GeneradorDeCodigo.generar("SWAP \n");
                    GeneradorDeCodigo.generar("STOREREF " + offset + "\n");
                    break;
                }            
            }            
        }
        
        if(tipoIzq == null)
            throw new ErrorSemantico("la variable '" + ladoIzq.getLexema() + "' no se encuentra definida. Linea: " + ladoIzq.getLinea());
        
        if(!tipoDer.conforma(tipoIzq))
            throw new ErrorSemantico("tipos no compatibles en asignacion, el tipo "+ tipoDer.getNombre() +" no conforma con " + tipoIzq.getNombre() +". Linea: " + ladoIzq.getLinea());              
        
        
        return tipoIzq;
    }
    
    
}
